#ifndef RAYTRACER_APP_H
#define RAYTRACER_APP_H

/**
 * @mainpage Ray-a-lity
 *
 * @version 1.42r78
 * @authors Emmanuel Bengio, Phillipe Nadeau, Gauthier Viau
 *
 * @section intro Introduction
 * Ce projet rassemble plusieurs fonctionnalités qui permettent de faire rouler un raytracer. Un raytracer permet de générer des images 3D à partir d'une géométrie prédéfinie. Ce projet rassemble donc un ensemble de classes à caractère géométrique, unies sous un type: Primitive. Ces objets géométriques font eux appel à un ensemble de classes et de fonctions définies dans un package mathématique, qui contient des classes telles que Math::Vector, Math::Ray et Math::Triangle.
 
 Grâce à ces classes il nous est possible de mettre en place un framework qui va permettre de charger des objets, de les mettre en place dans l'espace, puis de les tracer, avec Raytracer, pour obtenir une Image, qu'on peut sauver sous le format PNG.

 Lors de notre projet nous avons dû faire face à plusieurs problèmes. Notamment, la génération des images requiérait une vitesse acceptable d'exécution alors que les calculs se faisaient assez lentement. Nous avons, pour remédier à ce problème effectué une série d'optimisations algorithmiques, géométriques et mathématiques. Elles sont expliqués en détail dans notre document de référence (voir reference.pdf).
 */


#include "RaytracerApps.h"

#include "Raytracer.h"
#include "Thread.h"

class Image;
//class ThreadManager;

/**
* La classe RaytracerApp est un singleton qui représente l'application en tant que telle.
*/
class RAYTRACER_API RaytracerApp
{
	public:
        /**
         * Va chercher l'instance de l'application
         */
		static RaytracerApp* getInstance();
		~RaytracerApp();
        
        /**
         * initialise l'application
         */
		void init(std::string configPath);
        /**
         * trace l'image en lancant des Threads
         */
		Image* run();
        /**
         * sauve l'image tracée
         */
		void save(Image *img);
        
        /**
         * Met à jour la position de la caméra
         */
		void update(int key, float delta);
        /** retourne la largeur de l'image*/
		unsigned int getWidth() const { return m_Raytracer->getWidth(); }
        /** retourne la hauteur de l'image*/
		unsigned int getHeight() const { return m_Raytracer->getHeight(); }

        /** active le compteur dans ThreadManager */
        void activateCounter() const { m_ThreadManager->activateCounter();}
	private:
		static RaytracerApp		m_Instance;///< Instance du Singleton
		RaytracerApp();///< Constructeur privé

		Raytracer	   *m_Raytracer;		///< Instance du Raytracer
		ThreadManager  *m_ThreadManager;	///< Manager des threads de Raytracer

		std::string		m_ConfigPath;		///< Le chemin vers le config file en argument
}; // Class

#endif
